home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / gnuplot / contrib / russo / sopen_rw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-25  |  4.0 KB  |  141 lines

  1. /*
  2.  * Copyright (c) 1988 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software written by Ken Arnold and
  6.  * published in UNIX Review, Vol. 6, No. 8.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that: (1) source distributions retain this entire copyright
  10.  * notice and comment, and (2) distributions including binaries display
  11.  * the following acknowledgement:  ``This product includes software
  12.  * developed by the University of California, Berkeley and its contributors''
  13.  * in the documentation or other materials provided with the distribution
  14.  * and in all advertising materials mentioning features or use of this
  15.  * software. Neither the name of the University nor the names of its
  16.  * contributors may be used to endorse or promote products derived
  17.  * from this software without specific prior written permission.
  18.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  20.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  21.  */
  22.  
  23. #if defined(LIBC_SCCS) && !defined(lint)
  24. static char sccsid[] = "@(#)popen.c    5.14 (Berkeley) 6/1/90";
  25. #endif /* LIBC_SCCS and not lint */
  26.  
  27. #include <sys/param.h>
  28. #include <sys/signal.h>
  29. #include <sys/wait.h>
  30. #include <errno.h>
  31. #include <stdio.h>
  32. #include <unistd.h>
  33. #include <paths.h>
  34. #include <stdlib.h>
  35.  
  36. /*
  37.  * Original popen() code extended to open both
  38.  * read and write pipes to a process.
  39.  *
  40.  * By Kevin Russo  SFA, Inc/US Naval Research Lab, Code 5133
  41.  *                 March 14, 1991
  42.  *
  43.  * Calling sequence:
  44.  *      FILE ** popen_rw(const char *program)
  45.  *
  46.  *      Arguments:
  47.  *      program - a shell command
  48.  *
  49.  *      Returns:
  50.  *      FILE **ptr;
  51.  *
  52.  *      ptr[0] is a FILE pointer to the program's stdout (read here)
  53.  *      ptr[1] is a FILE pointer to the program's stdin  (write here)
  54.  *
  55.  *    Opens a read fd and a write fd, so popen()'s 'type'argument
  56.  *    is not necessary.
  57.  */
  58.  
  59. static pid_t *pids;
  60.  
  61. FILE **
  62. popen_rw(const char *program)
  63. {
  64.     FILE **iop;
  65.     int pdes[2], fds, pid;
  66.     int pdes2[2];
  67.  
  68.     if (pids == NULL) {
  69.         if ((fds = getdtablesize()) <= 0)
  70.             return (NULL);
  71.         if((pids = (pid_t *)malloc((u_int)(fds * sizeof(int)))) == NULL)
  72.             return (NULL);
  73.         bzero((char *)pids, fds * sizeof(pid_t));
  74.     }
  75.     if ((iop = (FILE **) malloc(2 * sizeof(FILE **))) == NULL)
  76.         return (NULL);
  77.  
  78.     if (pipe(pdes) < 0 || pipe(pdes2) < 0)
  79.         return (NULL);
  80.     switch (pid = fork()) {
  81.     case -1:            /* error */
  82.         (void) close(pdes[0]);
  83.         (void) close(pdes[1]);
  84.         (void) close(pdes2[0]);
  85.         (void) close(pdes2[1]);
  86.         return (NULL);
  87.         /* NOTREACHED */
  88.     case 0:                /* child */
  89.                 if (pdes[1] != STDOUT_FILENO) {
  90.                         (void) dup2(pdes[1], STDOUT_FILENO);
  91.                         (void) close(pdes[1]);
  92.                 }
  93.                 (void) close(pdes[0]);
  94.                 if (pdes2[0] != STDIN_FILENO) {
  95.                         (void) dup2(pdes2[0], STDIN_FILENO);
  96.                         (void) close(pdes2[0]);
  97.                 }
  98.                 (void) close(pdes2[1]);
  99.         execl(_PATH_BSHELL, "sh", "-c", program, NULL);
  100.         _exit(127);
  101.         /* NOTREACHED */
  102.     }
  103.     /* parent; assume fdopen can't fail...  */
  104.     iop[0] = fdopen(pdes[0], "r");
  105.     iop[1] = fdopen(pdes2[1], "w");
  106.     (void) close(pdes[1]);
  107.     (void) close(pdes2[0]);
  108.     pids[fileno(iop[0])] = pid;
  109.     pids[fileno(iop[1])] = pid;
  110.     return (iop);
  111. }
  112.  
  113. int pclose_rw(FILE *iop[])
  114. {
  115.     register int fdes,fdes2;
  116.     int omask;
  117.     /*union wait pstat;*/
  118.     int pstat;
  119.     pid_t pid;
  120.  
  121.     /*
  122.      * pclose returns -1 if stream is not associated with a
  123.      * `popened' command, if already `pclosed', or waitpid
  124.      * returns an error.
  125.      */
  126.     if (pids == NULL || pids[fdes = fileno(iop[0])] == 0 ||
  127.                 pids[fdes2 = fileno(iop[1])] == 0)
  128.         return (-1);
  129.     (void) fclose(iop[0]);
  130.     (void) fclose(iop[1]);
  131.     omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
  132.     do {
  133.         pid = waitpid(pids[fdes], &pstat, 0);
  134.     } while (pid == -1 && errno == EINTR);
  135.     (void) sigsetmask(omask);
  136.     pids[fdes] = 0;
  137.     pids[fdes2] = 0;
  138.     /*return (pid == -1 ? -1 : pstat.w_status);*/
  139.     return (pid == -1 ? -1 : pstat);
  140. }
  141.